package com.grm.handler;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.handler.codec.http.multipart.*;

import java.io.File;
import java.io.RandomAccessFile;

/**
 * 文件上传处理
 */
public class FileUploadHandler extends SimpleChannelInboundHandler<HttpRequest> {

    // 创建 HttpDataFactory 实例，用于处理 HTTP 数据
    private static final HttpDataFactory factory = new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE);

    /**
     * 处理入站 HTTP 请求
     *
     * @param ctx 上下文，用于访问通道、写数据等
     * @param msg 收到的 HTTP 请求
     * @throws Exception 可能抛出的异常
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpRequest msg) throws Exception {
        try {
            // 解析 HTTP 请求
            HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(factory, msg);
            try {
                decoder.offer((HttpContent) msg);

                // 文件上传处理
                boolean hasFiles = false;
                for (InterfaceHttpData data : decoder.getBodyHttpDatas()) {
                    if (data instanceof FileUpload fileUpload) {
                        hasFiles = true;
                        // 获取上传文件的文件名
                        String originalFileName = fileUpload.getFilename();
                        // 安全处理文件名，防止路径遍历攻击
                        String fileName = sanitizeFileName(originalFileName);
                        if (fileName == null) {
                            continue; // 跳过非法文件名
                        }

                        // 验证文件类型
                        if (!isValidFileType(fileName)) {
                            continue; // 跳过非法文件类型
                        }

                        // 检查文件是否为空
                        if (fileUpload.length() == 0) {
                            continue; // 跳过空文件
                        }

                        // 创建 RandomAccessFile 对象以写入上传的文件
                        try (RandomAccessFile file = new RandomAccessFile(new File("uploaded_files/" + fileName), "rw")) {
                            // 将上传的文件内容写入新文件中
                            file.write(fileUpload.getByteBuf().array());
                        }
                    }
                }

                // 返回响应
                HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, hasFiles ? HttpResponseStatus.OK : HttpResponseStatus.NO_CONTENT);
                ctx.writeAndFlush(response);
            } finally {
                decoder.destroy(); // 确保解码器被正确销毁
            }
        } catch (Exception e) {
            // 捕获并处理异常
            HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR);
            ctx.writeAndFlush(response);
            throw e; // 重新抛出异常以便进一步处理
        }
    }

    /**
     * 安全处理文件名，防止路径遍历攻击
     *
     * @param originalFileName 原始文件名
     * @return 处理后的文件名，如果文件名不合法则返回 null
     */
    private String sanitizeFileName(String originalFileName) {
        // 简单的路径遍历防护，实际应用中应更严格
        if (originalFileName.contains("..") || originalFileName.contains("/") || originalFileName.contains("\\")) {
            return null;
        }
        return originalFileName;
    }

    /**
     * 验证文件类型
     *
     * @param fileName 文件名
     * @return 是否为合法文件类型
     */
    private boolean isValidFileType(String fileName) {
        // 允许的文件扩展名列表
        String[] allowedExtensions = {".jpg", ".jpeg", ".png", ".gif"};
        for (String ext : allowedExtensions) {
            if (fileName.toLowerCase().endsWith(ext)) {
                return true;
            }
        }
        return false;
    }
}
